package com.ruoyi.apm.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.github.pagehelper.util.StringUtil;
import com.ruoyi.apm.dao.DockDataConfigMapper;
import com.ruoyi.apm.model.*;
import com.ruoyi.apm.quartz.DynamicJobManager;
import com.ruoyi.apm.service.DockDataConfigService;
import com.ruoyi.apm.service.HttpRequestService;
import com.ruoyi.apm.util.GuidGenerator;
import com.ruoyi.apm.util.MathUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.job.TaskException;
import com.ruoyi.common.utils.tree.TreeItem;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.ruoyi.apm.dao.HttpSequenceLogMapper;
import com.ruoyi.apm.dao.HttpSequenceMapper;
import com.ruoyi.apm.service.HttpSequenceService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;

@Service
public class HttpSequenceServiceImpl implements HttpSequenceService{

	@Autowired
	private HttpSequenceMapper httpSequenceMapper;
	@Autowired
	private HttpSequenceLogMapper httpSequenceLogMapper;

	@Autowired
	private DockDataConfigMapper dockDataConfigMapper;

	@Autowired
	private HttpRequestService httpRequestService;

	@Autowired
	private DockDataConfigService dockDataConfigService;

	@Autowired
	private Scheduler scheduler;

	@PostConstruct
	public void init() throws Exception {
		scheduler.clear();
		List<HttpSequence> list = httpSequenceMapper.selectAll();
		List<DockDataConfig> dataConfigs = dockDataConfigMapper.selectAll();
		if(list!=null&&list.size()>0){
			for(HttpSequence sequence:list){
				for(DockDataConfig dockDataConfig:dataConfigs){
					if(sequence.getGuid().equals(dockDataConfig.getGuid())){
						sequence.setDockDataConfig(dockDataConfig);
						break;
					}
				}
				if(sequence.getDockDataConfig()!=null){
					httpRequestService.initJob(sequence);
				}
			}
		}
	}
	
	@Override
	public HttpSequence getByGuid(String guid){
		return httpSequenceMapper.getByGuid(guid);
	}
	
	@Override
	public void archived(String guid){
		httpSequenceMapper.archived(guid);
	}
	
	@Override
	public void updateEnabled(HttpSequence httpSequence){
		httpSequenceMapper.updateEnabled(httpSequence);
	}
	
	@Override
	public void insert(HttpSequence httpSequence){
		if(StringUtil.isEmpty(httpSequence.getGuid())){
			httpSequence.setGuid(GuidGenerator.generate());
		}
		httpSequenceMapper.insert(httpSequence);
	}
	@Override
	public void update(HttpSequence httpSequence){
		httpSequenceMapper.update(httpSequence);
	}

	@Override
	public Map<String, Long> getAllJobCount(HttpSequence httpSequence) {
		return httpSequenceMapper.queryAllJobCount(httpSequence);
	}

	@Override
	public List<Map<String,Object>> getAllJob(HttpSequence httpSequence) {
		List<HttpSequence> list = httpSequenceMapper.selectAllJob(httpSequence);
		if(list==null||list.size()==0){
			return null;
		}
		List<String> guids = list.stream().map(e->e.getGuid()).collect(Collectors.toList());
		List<DockDataConfig> dataConfigs = dockDataConfigMapper.getDockDataConfigByGuids(guids);
		List<Map<String,Object>> result = new ArrayList<>();
		for(HttpSequence item : list){
			Map<String,Object> map = new HashMap<>();
			String guid = String.valueOf(item.getGuid());
			map.put("guid",guid);
			map.put("group",item.getGroup());
			map.put("name",item.getName());
			map.put("isEnabled",item.isEnabled());
			if(dataConfigs!=null&&dataConfigs.size()>0){
				for(DockDataConfig dockDataConfig:dataConfigs){
					if(item.getGuid().equals(dockDataConfig.getGuid())){
						map.put("cron",dockDataConfig.getCron());
					}
				}
			}
			//启动监控
			if(item.isEnabled()){
				//平均响应时间
				Object avgCostTime = httpSequenceLogMapper.selectAvgCostTimeByPguid(guid);
				map.put("avgCostTime", avgCostTime+"毫秒");
				//最近一次请求状态
				Object recentStatus = httpSequenceLogMapper.selectRecentStatusByPguid(guid);
				if(recentStatus == null){
					map.put("status", "--");
				}else{
					map.put("status", (boolean)recentStatus == true ? "正常" : "故障");
				}
				//可用率
				List<Map<String, Object>> usabilityList = httpSequenceLogMapper.selectUsabilityByPguid(guid);
				long count = 0;
				long uCount = 0;
				for(Map<String,Object> u : usabilityList){
					count += (long)u.get("count");
					if((boolean)u.get("status")){
						uCount+=(long)u.get("count");
					}
				}
				map.put("usability", MathUtil.percent(uCount, count));

			}else{
				//未启动
				map.put("status", "--");
				map.put("usability", "0%");
				map.put("avgCostTime", "0");
			}
			result.add(map);
		}
		return result;
	}

	@Override
	public List<Map<String, Object>> getMonitorList(String uuid){
		List<Map<String, Object>> list = httpSequenceMapper.selectMonitorList(uuid);
		for(Map<String,Object> item : list){
			item.put("frequency", MonitorFrequency.valueOf(item.get("frequency").toString()).getLabel());
			item.put("type", HttpSequence.getMonitorTypeName(String.valueOf(item.get("type"))));
			String guid = String.valueOf(item.get("guid"));
			//启动监控
			if((boolean)item.get("enabled")){
				//平均响应时间
				Object avgCostTime = httpSequenceLogMapper.selectAvgCostTimeByPguid(guid);
				item.put("avgCostTime", avgCostTime);
				//最近一次请求状态
				Object recentStatus = httpSequenceLogMapper.selectRecentStatusByPguid(guid);
				if(recentStatus == null){
					item.put("status", "未监控");
					item.put("textColor", "text-muted");
				}else{
					item.put("status", (boolean)recentStatus == true ? "正常" : "故障");
					item.put("textColor", (boolean)recentStatus == true ? "text-green" : "text-red");
				}
				//可用率
				List<Map<String, Object>> usabilityList = httpSequenceLogMapper.selectUsabilityByPguid(guid);
				long count = 0;
				long uCount = 0;
				for(Map<String,Object> u : usabilityList){
					count += (long)u.get("count");
					if((boolean)u.get("status")){
						uCount+=(long)u.get("count");
					}
				}
				item.put("usability", MathUtil.percent(uCount, count));
				
			}else{
				//未启动
				item.put("status", "未监控");
				item.put("textColor", "text-muted");
				item.put("usability", "0%");
				item.put("avgCostTime", "0");
			}
		}
		return list;
	}
	
	@Override
	public List<Map<String, Object>> getLogByGuid(String guid){
		
		List<Map<String, Object>> list = httpSequenceLogMapper.selectLogByPguid(guid);

		for(Map<String,Object> item : list){
			
		}
		return list;
		
	}



	@Override
	public boolean addHttpSystem(String group){
		HttpSystem httpSystem = new HttpSystem();
		httpSystem.setName(group);
		try{
			httpSequenceMapper.insertSystem(httpSystem);
			return true;
		}catch(Exception e){
			return false;
		}
		
	}

	@Override
	public List<HttpSystem> getAllSystem(){
		return httpSequenceMapper.selectAllSystem();
		
	}
	
	@Override
	public void insertLog(HttpSequenceLog httpSequenceLog){
		httpSequenceLogMapper.insert(httpSequenceLog);
	}
	
	@Override
	public void deleteLog(String pguid){
		httpSequenceLogMapper.delete(pguid);
	}

	@Override
	public void cleanLog(int day){
		httpSequenceLogMapper.cleanLogByDay(day);
		
	}

	@Override
	public DockDataConfig getDockDataConfig(String guid) {
		return dockDataConfigMapper.getByGuid(guid);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void eduitSaveHttpSequence(HttpSequence httpSequence) {
		//添加
		if(StringUtil.isEmpty(httpSequence.getGuid())){
			httpSequence.setGuid(GuidGenerator.generate());
			List<HttpRequest> httpRequests = httpSequence.getHttpRequest();
			for(HttpRequest request : httpRequests){
				request.setPguid(httpSequence.getGuid());
				httpRequestService.insertHttpRequest(request);
			}
			insert(httpSequence);
			DockDataConfig dockDataConfig = httpSequence.getDockDataConfig();
			dockDataConfig.setGuid(httpSequence.getGuid());
			dockDataConfigService.insert(dockDataConfig);
			//增加任务
			DynamicJobManager dynamicJobManager = new DynamicJobManager(httpSequence);
			dynamicJobManager.init();
		}else{
			//先删除任务
			DynamicJobManager dynamicJobManager = new DynamicJobManager(httpSequence);
			dynamicJobManager.deleteJobForUpdate();
			//修改
			List<HttpRequest> httpRequests = httpSequence.getHttpRequest();
			httpRequestService.archivedHttpRequest(httpSequence.getGuid());
			for(HttpRequest request : httpRequests){
				request.setPguid(httpSequence.getGuid());
				if(StringUtil.isEmpty(request.getGuid())){
					httpRequestService.insertHttpRequest(request);
				}else{
					httpRequestService.updateHttpRequest(request);
				}
			}
			this.update(httpSequence);
			DockDataConfig dockDataConfig = httpSequence.getDockDataConfig();
			dockDataConfig.setGuid(httpSequence.getGuid());
			dockDataConfigService.update(dockDataConfig);
			//增加任务
			dynamicJobManager = new DynamicJobManager(httpSequence);
			dynamicJobManager.init();
		}
	}

	@Override
	public List<TreeItem> queryTreeData() {
		return httpSequenceMapper.queryTreeData();
	}
}
